using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Terminal.Advanced_AEUC_settings_controls.Settings_AUX;
using Terminal.Advanced_AEUC_settings_controls.Settings_Interfaces;
using Terminal.Advanced_AEUC_settings_controls.Setting_Advanced_Control;
using System.IO;

namespace Terminal.Advanced_AEUC_settings_controls.Settings_Editing_Forms
{
    /// <summary>
    /// Form for message managment
    /// </summary>
    public partial class AEUCMessages : Form
    {
        #region Message mapping
        const int OMX_GET_COMP_HDL = 0;
        const int OMX_GET_COMP_PORTS = 1;
        const int OMX_ALLOC_PORT_BUFFS = 2;
        const int OMX_LINK_COMP_PORTS = 3;
        const int OMX_COMP_COMMANDS = 4;
        const int OMX_COMP_GET_CONF = 5;
        const int OMX_COMP_SET_CONF = 6;
        const int OMX_COMP_GET_PARAM = 7;
        const int OMX_COMP_SET_PARAM = 8;
        const int SYS_DATA_MSG = 9;
        const int SYS_MARSHALL_ALLOC = 10;
        const int SYS_MARSHALL_FREE = 11;
        const int SYS_MARSHALL_COPY = 12;
        const int SYS_MARSHALL_DUMP = 13;
        const int SYS_MARSHALL_ALLOC_TYPE = 14;
        string[] mapAsMsdOptions = new string[] { "OMX Get component handle",
                                                    "OMX Get component ports",
                                                    "OMX Alloc port buffers",
                                                    "OMX Link components ports",
                                                    "OMX Component commands",
                                                    "OMX Get configuration",
                                                    "OMX Set configuration",
                                                    "OMX Get parameter",
                                                    "OMX Set parameter",
                                                    "System data transfer",
                                                    "Marshalling memory allocate",
                                                    "Marshalling memory free",
                                                    "Marshalling memory copy",
                                                    "Marshalling memory dump",
                                                    "Marshalling memory allocation type"};
        #endregion
        #region Status mapping
        const int STS_DATA_INIT = 0;
        const int STS_DATA_FULL = 1;
        const int STS_DATA_START = 2;
        const int STS_DATA_MORE = 3;
        const int STS_DATA_END = 4;
        const int STS_DATA_TYPE_JPEG = 5;
        const int STS_DATA_TYPE_INFO = 6;
        string[] mapAsSTSOptions = new string[] { "System data transfer init",
                                                    "System data full packet",
                                                    "System data start packet",
                                                    "System data partial packet",
                                                    "System data final packet",
                                                    "System data type JPEG",
                                                    "System data type INFO",};
        #endregion
        AEUCTabbedParentControl prntAssociate;
        /// <summary>
        /// Creates an instance of the message managment form
        /// </summary>
        /// <param name="iprntAssociate">The parent advanced tabbed control that the messages belong to</param>
        public AEUCMessages(AEUCTabbedParentControl iprntAssociate)
        {
            InitializeComponent();
            prntAssociate = iprntAssociate;
            for (int i = 0; i < mapAsMsdOptions.Length; i++)
            {
                cbMapAsMsgOpts.Items.Add(mapAsMsdOptions[i]);
            }
            if (cbMapAsMsgOpts.Items.Count > 0)
                cbMapAsMsgOpts.SelectedIndex = 0;

            for (int i = 0; i < mapAsSTSOptions.Length; i++)
            {
                cbMapAsSTSOpts.Items.Add(mapAsSTSOptions[i]);
            }
            if (cbMapAsSTSOpts.Items.Count > 0)
                cbMapAsSTSOpts.SelectedIndex = 0;
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            Close();
        }

        #region Add/Remove message ids/states/destinations
        private void btnAEUCMSGId_Click(object sender, EventArgs e)
        {
            AEUCAddMSGItem aam = new AEUCAddMSGItem(prntAssociate.cmcDefinitios, AEUCAddMSGItem.MSGItemType.AEUC_MSG_ID);
            aam.ShowDialog();
            ReloadAEUCItems();
        }

        private void btnAEUCMSGIdEdit_Click(object sender, EventArgs e)
        {
            if(lbAEUCMSGId.SelectedItem != null)
            {
                AEUCAddMSGItem aam = new AEUCAddMSGItem(prntAssociate.cmcDefinitios, (GenMSGId)lbAEUCMSGId.SelectedItem);
                aam.ShowDialog();
            }
        }

        private void btnAEUCMSGIdRemove_Click(object sender, EventArgs e)
        {
            if (lbAEUCMSGId.SelectedIndex > -1)
            {
                prntAssociate.cmcDefinitios.AEUC_MSG_ID.Remove((GenMSGId)lbAEUCMSGId.SelectedItem);
                ReloadAEUCItems();
            }
        }

        private void btnAEUCMSGStat_Click(object sender, EventArgs e)
        {
            AEUCAddMSGItem aam = new AEUCAddMSGItem(prntAssociate.cmcDefinitios, AEUCAddMSGItem.MSGItemType.AEUC_MSG_STAT);
            aam.ShowDialog();
            ReloadAEUCItems();
        }

        private void btnAEUCMSGStatEdit_Click(object sender, EventArgs e)
        {
            if (lbAEUCMSGStat.SelectedItem != null)
            {
                AEUCAddMSGItem aam = new AEUCAddMSGItem(prntAssociate.cmcDefinitios, (GenMSGStatus)lbAEUCMSGStat.SelectedItem);
                aam.ShowDialog();
            }
        }

        private void btnAEUCMSGStatRemove_Click(object sender, EventArgs e)
        {
            if (lbAEUCMSGStat.SelectedIndex > -1)
            {
                prntAssociate.cmcDefinitios.AEUC_MSG_STAT.Remove((GenMSGStatus)lbAEUCMSGStat.SelectedItem);
                ReloadAEUCItems();
            }
        }

        private void btnSPECMSGMSGId_Click(object sender, EventArgs e)
        {
            AEUCAddMSGItem aam = new AEUCAddMSGItem(prntAssociate.cmcDefinitios, AEUCAddMSGItem.MSGItemType.SPECMSG_MSG_ID);
            aam.ShowDialog();
            ReloadSPECMSGItems();
        }

        private void btnSPECMSGMSGIdEdit_Click(object sender, EventArgs e)
        {
            if (lbSPECMSGMSGId.SelectedItem != null)
            {
                AEUCAddMSGItem aam = new AEUCAddMSGItem(prntAssociate.cmcDefinitios, (GenMSGId)lbSPECMSGMSGId.SelectedItem);
                aam.ShowDialog();
            }
        }

        private void btnSPECMSGMSGIdRemove_Click(object sender, EventArgs e)
        {
            if (lbSPECMSGMSGId.SelectedIndex > -1)
            {
                prntAssociate.cmcDefinitios.SPECMSG_MSG_ID.Remove((GenMSGId)lbSPECMSGMSGId.SelectedItem);
                ReloadSPECMSGItems();
            }
        }

        private void btnSPECMSGMSGStat_Click(object sender, EventArgs e)
        {
            AEUCAddMSGItem aam = new AEUCAddMSGItem(prntAssociate.cmcDefinitios, AEUCAddMSGItem.MSGItemType.SPECMSG_MSG_STAT);
            aam.ShowDialog();
            ReloadSPECMSGItems();
        }

        private void btnSPECMSGMSGStatEdit_Click(object sender, EventArgs e)
        {
            if (lbSPECMSGMSGStat.SelectedItem != null)
            {
                AEUCAddMSGItem aam = new AEUCAddMSGItem(prntAssociate.cmcDefinitios, (GenMSGStatus)lbSPECMSGMSGStat.SelectedItem);
                aam.ShowDialog();
            }
        }

        private void btnSPECMSGMSGStatRemove_Click(object sender, EventArgs e)
        {
            if (lbSPECMSGMSGStat.SelectedIndex > -1)
            {
                prntAssociate.cmcDefinitios.SPECMSG_MSG_STAT.Remove((GenMSGStatus)lbSPECMSGMSGStat.SelectedItem);
                ReloadSPECMSGItems();
            }
        }

        private void btnAddMSGDest_Click(object sender, EventArgs e)
        {
            AEUCAddMSGItem aam = new AEUCAddMSGItem(prntAssociate.cmcDefinitios, AEUCAddMSGItem.MSGItemType.MSG_DEST);
            aam.ShowDialog();
            ReloadMSGDest();
        }
        private void btnRemoveMSGDest_Click(object sender, EventArgs e)
        {
            if (lbMSGDest.SelectedIndex > -1)
            {
                prntAssociate.cmcDefinitios.MSG_DEST.Remove((GenMSGDestination)lbMSGDest.SelectedItem);
                ReloadMSGDest();
            }
        }
        #endregion

        #region Create/Remove Message definitions
        private void btnCrntMSGAdd_Click(object sender, EventArgs e)
        {
            AEUCMessageDefinition amd = new AEUCMessageDefinition(prntAssociate);
            amd.ShowDialog();
            ReloadCurntMSG();
        }

        private void btnCrntMSGEdit_Click(object sender, EventArgs e)
        {
            if (chlbCurrentMSG.SelectedIndex > -1)
            {
                GenMSG msgEdit = (GenMSG)chlbCurrentMSG.SelectedItem;
                AEUCEditMessageDefinition amdEdit = new AEUCEditMessageDefinition(prntAssociate, msgEdit);
                amdEdit.ShowDialog();
            }
        }

        private void btnCrntMSGRemove_Click(object sender, EventArgs e)
        {
            if (chlbCurrentMSG.CheckedItems.Count > 0)
            {
                for (int i = 0; i<chlbCurrentMSG.CheckedItems.Count; i++)
                {
                    GenMSG msgRem = (GenMSG)chlbCurrentMSG.CheckedItems[i];
                    if (msgRem.msgDestination == prntAssociate.cmcDefinitios.MSG_DEST_AEUC)
                    {
                        prntAssociate.cmcDefinitios.AEUC_MSG.Remove(msgRem);
                    }
                    else if (msgRem.msgDestination == prntAssociate.cmcDefinitios.MSG_DEST_SPECMSG)
                    {
                        prntAssociate.cmcDefinitios.SPECMSG_MSG.Remove(msgRem);
                    }
                    else
                    {
                        prntAssociate.cmcDefinitios.AEUC_MSG.Remove(msgRem);
                    }
                }
                ReloadCurntMSG();
            }
            else if (chlbCurrentMSG.SelectedIndex > -1)
            {
                GenMSG msgRem = (GenMSG)chlbCurrentMSG.SelectedItem;
                if (msgRem.msgDestination == prntAssociate.cmcDefinitios.MSG_DEST_AEUC)
                {
                    prntAssociate.cmcDefinitios.AEUC_MSG.Remove(msgRem);
                }
                else if (msgRem.msgDestination == prntAssociate.cmcDefinitios.MSG_DEST_SPECMSG)
                {
                    prntAssociate.cmcDefinitios.SPECMSG_MSG.Remove(msgRem);
                }
                else
                {
                    prntAssociate.cmcDefinitios.AEUC_MSG.Remove(msgRem);
                }
                ReloadCurntMSG();
            }
        }
        #endregion

        #region UI updating to content changes
        private void AEUCMessages_Load(object sender, EventArgs e)
        {
            ReloadAllUI();
        }
        /// <summary>
        /// Forces the UI to reaload, dereferencing instances anew
        /// </summary>
        public void ReloadAllUI()
        {
            ReloadCurntMSG();

            ReloadAEUCItems();

            ReloadSPECMSGItems();

            ReloadMSGDest();

            tbDefineStartChr.Text = prntAssociate.cmcDefinitios.MSG_START_CHAR.ToString();

            tbSetDelimitor.Text = prntAssociate.cmcDefinitios.SettingDelimitor.ToString();
        }

        void ReloadCurntMSG()
        {
            chlbCurrentMSG.Items.Clear();
            #region Add existant messages
            for (int i =0; i<prntAssociate.cmcDefinitios.AEUC_MSG.Count; i++)
            {
                chlbCurrentMSG.Items.Add(prntAssociate.cmcDefinitios.AEUC_MSG[i]);
            }
            for (int i =0; i<prntAssociate.cmcDefinitios.SPECMSG_MSG.Count; i++)
            {
                chlbCurrentMSG.Items.Add(prntAssociate.cmcDefinitios.SPECMSG_MSG[i]);
            }
            #endregion
        }

        void ReloadAEUCItems()
        {
            lbAEUCMSGId.Items.Clear();
            lbAEUCMSGStat.Items.Clear();
            #region Add AEUC message items
            for (int i =0; i<prntAssociate.cmcDefinitios.AEUC_MSG_ID.Count; i++)
            {
                lbAEUCMSGId.Items.Add(prntAssociate.cmcDefinitios.AEUC_MSG_ID[i]);
            }
            for (int i =0; i<prntAssociate.cmcDefinitios.AEUC_MSG_STAT.Count; i++)
            {
                lbAEUCMSGStat.Items.Add(prntAssociate.cmcDefinitios.AEUC_MSG_STAT[i]);
            }
            #endregion
        }

        void ReloadSPECMSGItems()
        {
            lbSPECMSGMSGId.Items.Clear();
            lbSPECMSGMSGStat.Items.Clear();
            #region Add SPECMSG message items
            for (int i =0; i<prntAssociate.cmcDefinitios.SPECMSG_MSG_ID.Count; i++)
            {
                lbSPECMSGMSGId.Items.Add(prntAssociate.cmcDefinitios.SPECMSG_MSG_ID[i]);
            }
            for (int i =0; i<prntAssociate.cmcDefinitios.SPECMSG_MSG_STAT.Count; i++)
            {
                lbSPECMSGMSGStat.Items.Add(prntAssociate.cmcDefinitios.SPECMSG_MSG_STAT[i]);
            }
            #endregion
        }

        void ReloadMSGDest()
        {
            lbMSGDest.Items.Clear();
            #region Add message targets
            for (int i =0; i<prntAssociate.cmcDefinitios.MSG_DEST.Count; i++)
            {
                lbMSGDest.Items.Add(prntAssociate.cmcDefinitios.MSG_DEST[i]);
            }
            #endregion
        }
        #endregion

        private void btnSetDelimiter_Click(object sender, EventArgs e)
        {
            UInt16 set_del;

            if (UInt16.TryParse(tbSetDelimitor.Text, out set_del))
            {
                prntAssociate.cmcDefinitios.SettingDelimitor = set_del;
            }
            else
                MessageBox.Show("Please input a valid setting delimiter value.");
        }

        private void btnDefineStartChr_Click(object sender, EventArgs e)
        {
            Byte set_del;
      
            if (Byte.TryParse(tbSetDelimitor.Text, out set_del))
            {
                prntAssociate.cmcDefinitios.MSG_START_CHAR = set_del;
            }
            else
                MessageBox.Show("Please input a valid starting character.");
        }

        private void btnMapAEUC_Click(object sender, EventArgs e)
        {
            if (lbMSGDest.SelectedIndex > -1)
            {
                prntAssociate.cmcDefinitios.MSG_DEST_AEUC = (GenMSGDestination)lbMSGDest.SelectedItem;
            }
        }

        private void btnMapSPECMSG_Click(object sender, EventArgs e)
        {
            if (lbMSGDest.SelectedIndex > -1)
            {
                prntAssociate.cmcDefinitios.MSG_DEST_SPECMSG = (GenMSGDestination)lbMSGDest.SelectedItem;
            }
        }

        private void chlbCurrentMSG_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (chlbCurrentMSG.SelectedItem != null)
            {
                pnlMapAsMSG.Enabled = true;
            }
            else
            {
                pnlMapAsMSG.Enabled = false;
            }
        }

        private void btnMapAs_Click(object sender, EventArgs e)
        {
            if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[OMX_GET_COMP_HDL])
            {
                prntAssociate.cmcDefinitios.msgOMXGetCompInstance = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[OMX_GET_COMP_PORTS])
            {
                prntAssociate.cmcDefinitios.msgOMXGetCompPorts = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[OMX_ALLOC_PORT_BUFFS])
            {
                prntAssociate.cmcDefinitios.msgOMXAllocPortBuffs = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[OMX_LINK_COMP_PORTS])
            {
                prntAssociate.cmcDefinitios.msgOMXLinkCompPorts = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[OMX_COMP_COMMANDS])
            {
                prntAssociate.cmcDefinitios.msgOMXCompCmds = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[SYS_DATA_MSG])
            {
                prntAssociate.cmcDefinitios.msgSYSDataMsg = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[OMX_COMP_GET_CONF])
            {
                prntAssociate.cmcDefinitios.msgOMXGetCompConf = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[OMX_COMP_SET_CONF])
            {
                prntAssociate.cmcDefinitios.msgOMXSetCompConf = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[OMX_COMP_GET_PARAM])
            {
                prntAssociate.cmcDefinitios.msgOMXGetCompParam = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[OMX_COMP_SET_PARAM])
            {
                prntAssociate.cmcDefinitios.msgOMXSetCompParam = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[SYS_MARSHALL_ALLOC])
            {
                prntAssociate.cmcDefinitios.msgSYSMarshalAlloc = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[SYS_MARSHALL_FREE])
            {
                prntAssociate.cmcDefinitios.msgSYSMarshalFree = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[SYS_MARSHALL_COPY])
            {
                prntAssociate.cmcDefinitios.msgSYSMarshalCopy = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[SYS_MARSHALL_DUMP])
            {
                prntAssociate.cmcDefinitios.msgSYSMarshalDump = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
            else if ((string)cbMapAsMsgOpts.SelectedItem == mapAsMsdOptions[SYS_MARSHALL_ALLOC_TYPE])
            {
                prntAssociate.cmcDefinitios.msgSYSMarshalAllocType = (GenMSG)chlbCurrentMSG.SelectedItem;
            }
        }

        private void lbAEUCMSGStat_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lbAEUCMSGStat.SelectedItem != null)
            {
                pnlMapAsSTS.Enabled = true;
            }
            else
            {
                pnlMapAsSTS.Enabled = false;
            }
        }

        private void btnMapAsSTS_Click(object sender, EventArgs e)
        {
            if ((string)cbMapAsSTSOpts.SelectedItem == mapAsSTSOptions[STS_DATA_INIT])
            {
                prntAssociate.cmcDefinitios.msgCtrlStatDataInit = (GenMSGStatus)lbAEUCMSGStat.SelectedItem;
            }
            else if ((string)cbMapAsSTSOpts.SelectedItem == mapAsSTSOptions[STS_DATA_FULL])
            {
                prntAssociate.cmcDefinitios.msgCtrlStatDataFull = (GenMSGStatus)lbAEUCMSGStat.SelectedItem;
            }
            else if ((string)cbMapAsSTSOpts.SelectedItem == mapAsSTSOptions[STS_DATA_START])
            {
                prntAssociate.cmcDefinitios.msgCtrlStatDataStart = (GenMSGStatus)lbAEUCMSGStat.SelectedItem;
            }
            else if ((string)cbMapAsSTSOpts.SelectedItem == mapAsSTSOptions[STS_DATA_MORE])
            {
                prntAssociate.cmcDefinitios.msgCtrlStatDataMore = (GenMSGStatus)lbAEUCMSGStat.SelectedItem;
            }
            else if ((string)cbMapAsSTSOpts.SelectedItem == mapAsSTSOptions[STS_DATA_END])
            {
                prntAssociate.cmcDefinitios.msgCtrlStatDataEnd = (GenMSGStatus)lbAEUCMSGStat.SelectedItem;
            }
            else if ((string)cbMapAsSTSOpts.SelectedItem == mapAsSTSOptions[STS_DATA_TYPE_JPEG])
            {
                prntAssociate.cmcDefinitios.msgCtrlStatDataTypeJpeg = (GenMSGStatus)lbAEUCMSGStat.SelectedItem;
            }
            else if ((string)cbMapAsSTSOpts.SelectedItem == mapAsSTSOptions[STS_DATA_TYPE_INFO])
            {
                prntAssociate.cmcDefinitios.msgCtrlStatDataTypeInfo = (GenMSGStatus)lbAEUCMSGStat.SelectedItem;
            }
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            prntAssociate.SaveCMCExport();
        }

        private void btnImport_Click(object sender, EventArgs e)
        {
            prntAssociate.LoadCMCExport();
            ReloadAllUI();
        }

        #region OBSOLETE - FORCES FULL AUEC SERIALIZE/DESERIALIZE "Save/Load messages to xml file"

        /// <summary>
        /// Saves a user setting definition file
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">Event arguments</param>
        public void btnSave_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.AddExtension = true;
            sfd.DefaultExt = "tsd";
            sfd.Filter = "*.tsd|*.tsd";
            
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                BinaryWriter binWrt = null;
                try
                {
                    FileInfo saveFile = new FileInfo(sfd.FileName);
                    binWrt = new BinaryWriter(saveFile.Create());
                    ((IAEUCSerialization)prntAssociate).Serialize(binWrt);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    binWrt.Close();
                }
            }
        }

        /// <summary>
        /// Loads a user setting definition file
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">Event arguments</param>
        public void btnLoad_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.DefaultExt = "tsd";
            ofd.Filter = "*.tsd|*.tsd";
            
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                BinaryReader binRdr = null;
                try
                {
                    FileInfo loadFile = new FileInfo(ofd.FileName);
                    binRdr = new BinaryReader(loadFile.OpenRead());
                    if (loadFile.Exists)
                    {
                        prntAssociate.ClrTabPages();
                        ((IAEUCSerialization)prntAssociate).Deserialize(binRdr);
                    }
                    ReloadAllUI();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    binRdr.Close();
                }
            }
        }

        #endregion
    }
}